#include "NewTerrainContentsGenerator23.h"
#include "Terrain/ScSimplexNoise.h"

#include <algorithm>
#include <cfloat>
#include "Engine/MathUtils.hpp"

#include "Managers/BlocksManager.h"
#include "Managers/PlantsManager.h"

#include "Subsystems/SubsystemGameInfo.h"
#include "Subsystems/SubsystemTerrain.h"
#include "Subsystems/SubsystemWeather.h"

#include "GameSingleton.h"
#include "Engine/Random.hpp"
#include "Log.h"
#include "Blocks/FluidBlock.h"
#include "Blocks/WoodBlock.h"
#include "Blocks/WaterBlock.h"
#include "Blocks/IvyBlock.h"
#include "Blocks/SpikedPlankBlock.h"
#include "Blocks/StairsBlock.h"
#include "Blocks/GravestoneBlock.h"
#include "Blocks/BottomSuckerBlock.h"

#include "Blocks/OakLeavesBlock.h"
#include "Blocks/BirchLeavesBlock.h"
#include "Blocks/MimosaLeavesBlock.h"
#include "Blocks/SpruceLeavesBlock.h"
#include "Blocks/TallSpruceLeavesBlock.h"

#include "Log.h"

namespace PocketSurvival
{
    struct CavePoint
    {
        Vector3 position;
        Vector3 direction;
        int32_t brushType;
        int32_t length;
        int32_t stepsTaken;

        CavePoint(const Vector3 &thePosition, const Vector3 &thedirection, int32_t theBrushType, int32_t theLength, int32_t thestepsTaken);
    };

    inline CavePoint::CavePoint(const Vector3 &thePosition, const Vector3 &thedirection, int32_t theBrushType, int32_t theLength, int32_t thestepsTaken) : position(thePosition), direction(thedirection), brushType(theBrushType), length(theLength), stepsTaken(thestepsTaken) {}

    class Grid2d
    {
    public:
        int32_t sizeX;
        int32_t sizeY;
        float *dataBuff;

        Grid2d(int32_t theSizeX, int32_t theSizeY) : sizeX(theSizeX), sizeY(theSizeY)
        {
            dataBuff = new float[sizeX * sizeY];
        }
        ~Grid2d()
        {
            delete dataBuff;
        }
        inline float get(int32_t x, int32_t y)
        {
            return dataBuff[x + y * sizeX];
        }
        inline void set(int32_t x, int32_t y, float value)
        {
            dataBuff[x + y * sizeX] = value;
        }
    };

    class Grid3d
    {
    public:
        int32_t sizeX;
        int32_t sizeY;
        int32_t sizeZ;
        int32_t sizeXY;

        float *dataBuff;

        Grid3d(int32_t theSizeX, int32_t theSizeY, int32_t theSizeZ) : sizeX(theSizeX), sizeY(theSizeY), sizeZ(theSizeZ)
        {
            sizeXY = sizeX * sizeY;
            dataBuff = new float[sizeX * sizeY * sizeZ];
        }
        ~Grid3d()
        {
            delete dataBuff;
        }

        void get8Value(int32_t x, int32_t y, int32_t z, float *outValueBuff)
        {
            int32_t num = x + y * sizeX + z * sizeXY;
            outValueBuff[0] = dataBuff[num];
            outValueBuff[1] = dataBuff[num + 1];
            outValueBuff[2] = dataBuff[num + sizeX];
            outValueBuff[3] = dataBuff[num + 1 + sizeX];
            outValueBuff[4] = dataBuff[num + sizeXY];
            outValueBuff[5] = dataBuff[num + 1 + sizeXY];
            outValueBuff[6] = dataBuff[num + sizeX + sizeXY];
            outValueBuff[7] = dataBuff[num + 1 + sizeX + sizeXY];
        }

        void set(int32_t x, int32_t y, int32_t z, float value)
        {
            dataBuff[x + y * sizeX + z * sizeXY] = value;
        }
    };

    NewTerrainContentsGenerator23::~NewTerrainContentsGenerator23() {}

    uint32_t NewTerrainContentsGenerator23::getOceanLevel()
    {
        return 64 + subsystemGameInfo->seaLevelOffset;
    }

    NewTerrainContentsGenerator23::NewTerrainContentsGenerator23()
    {
        CreateBrushes();
        subsystemGameInfo = GameSingleton::singletonPtr->getSingleton<SubsystemGameInfo>();
        subsystemTerrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();

        m_seed = subsystemGameInfo->worldSeed;
        m_islandSize = subsystemGameInfo->islandSize;

        Random random(m_seed);
        float num = (subsystemGameInfo->terrainGenerationMode == TerrainGenerationMode::Island ? MathUtils::Min(m_islandSize.posX, m_islandSize.posY) : FLT_MAX);
        m_oceanCorner = Vector2(-200.0f, -200.0f);
        m_temperatureOffset = Vector2(random.getFloat(-3000.0f, 3000.0f), random.getFloat(-3000.0f, 3000.0f));
        m_humidityOffset = Vector2(random.getFloat(-3000.0f, 3000.0f), random.getFloat(-3000.0f, 3000.0f));
        m_mountainsOffset = Vector2(random.getFloat(-3000.0f, 3000.0f), random.getFloat(-3000.0f, 3000.0f));
        m_riversOffset = Vector2(random.getFloat(-3000.0f, 3000.0f), random.getFloat(-3000.0f, 3000.0f));
        TGBiomeScaling = ((subsystemGameInfo->terrainGenerationMode == TerrainGenerationMode::Island) ? 1.0f : 1.75f) * subsystemGameInfo->biomeSize;
        TGShoreFluctuations = MathUtils::Clamp(2.0f * num, 0.0f, 150.0f);
        TGShoreFluctuationsScaling = MathUtils::Clamp(0.04f * num, 0.5f, 3.0f);
        TGOceanSlope = 0.006f;
        TGOceanSlopeVariation = 0.004f;

        TGIslandsFrequency = 0.01f;
        TGDensityBias = 55.0f;
        TGHeightBias = 1.0f;
        TGRiversStrength = 1.0f;
        TGMountainsStrength = 220.0f;
        TGMountainRangeFreq = 0.0006f;
        TGMountainsPercentage = 0.13f;
        TGMountainsDetailFreq = 0.003f;
        TGMountainsDetailOctaves = 3;
        TGMountainsDetailPersistence = 0.53f;
        TGHillsPercentage = 0.3f;
        TGHillsStrength = 32.0f;
        TGHillsOctaves = 1;
        TGHillsFrequency = 0.014f;
        TGHillsPersistence = 0.5f;
        TGTurbulenceStrength = 55.0f;
        TGTurbulenceFreq = 0.03f;
        TGTurbulenceOctaves = 1;
        TGTurbulencePersistence = 0.5f;
        TGMinTurbulence = 0.04f;
        TGTurbulenceZero = 0.84f;
        TGSurfaceMultiplier = 2.0f;
        TGWater = true;
        TGExtras = true;
        TGCavesAndPockets = true;
    }

    Vector3 NewTerrainContentsGenerator23::findCoarseSpawnPosition()
    {
        return FastVector3::Zero;
    }

    // ok
    float NewTerrainContentsGenerator23::calculateOceanShoreX(float z)
    {
        return m_oceanCorner.posX + TGShoreFluctuations * ScSimplexNoise::OctavedNoise(z, 0.0f, 0.005f / TGShoreFluctuationsScaling, 4, 1.95f, 1.0f);
    }
    // ok
    float NewTerrainContentsGenerator23::calculateOceanShoreZ(float x)
    {
        return m_oceanCorner.posY + TGShoreFluctuations * ScSimplexNoise::OctavedNoise(0.0f, x, 0.005f / TGShoreFluctuationsScaling, 4, 1.95f, 1.0f);
    }
    // ok
    float NewTerrainContentsGenerator23::calculateOceanShoreDistance(float x, float z)
    {
        if (subsystemGameInfo->terrainGenerationMode == TerrainGenerationMode::Island)
        {
            float num = calculateOceanShoreX(z);
            float num2 = calculateOceanShoreZ(x);
            float num3 = calculateOceanShoreX(z + 1000.0f) + m_islandSize.posX;
            float num4 = calculateOceanShoreZ(x + 1000.0f) + m_islandSize.posY;
            return MathUtils::Min(x - num, z - num2, num3 - x, num4 - z);
        }
        float num5 = calculateOceanShoreX(z);
        float num6 = calculateOceanShoreZ(x);
        return MathUtils::Min(x - num5, z - num6);
    }
    // ok
    static inline float Squish(float v, float zero, float one)
    {
        return MathUtils::Saturate((v - zero) / (one - zero));
    }
    // ok
    float NewTerrainContentsGenerator23::calculateHeight(float x, float z)
    {
        float num = TGOceanSlope + TGOceanSlopeVariation * MathUtils::PowSign(2.0f * ScSimplexNoise::OctavedNoise(x + m_mountainsOffset.posX, z + m_mountainsOffset.posY, 0.01f, 1, 2.0f, 0.5f) - 1.0f, 0.5f);
        float num2 = calculateOceanShoreDistance(x, z);
        float num3 = MathUtils::Saturate(2.0f - 0.05f * MathUtils::Abs(num2));
        float num4 = MathUtils::Saturate(MathUtils::Sin(TGIslandsFrequency * num2));
        float num5 = MathUtils::Saturate(MathUtils::Saturate((0.0f - num) * num2) - 0.85f * num4);
        float num6 = MathUtils::Saturate(MathUtils::Saturate(0.05f * (0.0f - num2 - 10.0f)) - num4);
        float v = calculateMountainRangeFactor(x, z);
        float f = (1.0f - num3) * ScSimplexNoise::OctavedNoise(x, z, 0.001f / TGBiomeScaling, 2, 2.0f, 0.5f);
        float f2 = (1.0f - num3) * ScSimplexNoise::OctavedNoise(x, z, 0.0017f / TGBiomeScaling, 2, 4.0f, 0.7f);
        float num7 = (1.0f - num6) * (1.0f - num3) * Squish(v, 1.0f - TGHillsPercentage, 1.0f - TGMountainsPercentage);
        float num8 = (1.0f - num6) * Squish(v, 1.0f - TGMountainsPercentage, 1.0f);
        float num9 = 1.0f * ScSimplexNoise::OctavedNoise(x, z, TGHillsFrequency, TGHillsOctaves, 1.93f, TGHillsPersistence);
        float amplitudeStep = MathUtils::Lerp(0.75f * TGMountainsDetailPersistence, 1.33f * TGMountainsDetailPersistence, f);
        float num10 = 1.5f * ScSimplexNoise::OctavedNoise(x, z, TGMountainsDetailFreq, TGMountainsDetailOctaves, 1.98f, amplitudeStep) - 0.5f;
        float num11 = MathUtils::Lerp(60.0f, 30.0f, MathUtils::Saturate(1.0f * num8 + 0.5f * num7 + MathUtils::Saturate(1.0f - num2 / 30.0f)));
        float x2 = MathUtils::Lerp(-2.0f, -4.0f, MathUtils::Saturate(num8 + 0.5f * num7));
        float num12 = MathUtils::Saturate(1.5f - num11 * MathUtils::Abs(2.0f * ScSimplexNoise::OctavedNoise(x + m_riversOffset.posX, z + m_riversOffset.posY, 0.001f, 4, 2.0f, 0.5f) - 1.0f));
        float num13 = -50.0f * num5 + TGHeightBias;
        float num14 = MathUtils::Lerp(0.0f, 8.0f, f);
        float num15 = MathUtils::Lerp(0.0f, -6.0f, f2);
        float num16 = TGHillsStrength * num7 * num9;
        float num17 = TGMountainsStrength * num8 * num10;
        float f3 = TGRiversStrength * num12;
        float num18 = num13 + num14 + num15 + num17 + num16;
        float num19 = MathUtils::Min(MathUtils::Lerp(num18, x2, f3), num18);
        return MathUtils::Clamp(64.0f + num19, 10.0f, 251.0f);
    }

    // ok
    int32_t NewTerrainContentsGenerator23::calculateTemperature(float x, float z)
    {
        return MathUtils::Clamp<int32_t>((MathUtils::Saturate(3.0f * ScSimplexNoise::OctavedNoise(x + m_temperatureOffset.posX, z + m_temperatureOffset.posY, 0.0015f / TGBiomeScaling, 5, 2.0f, 0.6f) - 1.1f + subsystemGameInfo->temperatureOffset / 16.0f) * 16.0f), 0, 15);
    }
    // ok
    int32_t NewTerrainContentsGenerator23::calculateHumidity(float x, float z)
    {
        return MathUtils::Clamp<int32_t>((MathUtils::Saturate(3.0f * ScSimplexNoise::OctavedNoise(x + m_humidityOffset.posX, z + m_humidityOffset.posY, 0.0012f / TGBiomeScaling, 5, 2.0f, 0.6f) - 0.9f + subsystemGameInfo->humidityOffset / 16.0f) * 16.0f), 0, 15);
    }
    // ok
    float NewTerrainContentsGenerator23::calculateMountainRangeFactor(float x, float z)
    {
        return ScSimplexNoise::OctavedNoise(x + m_mountainsOffset.posX, z + m_mountainsOffset.posY, TGMountainRangeFreq / TGBiomeScaling, 3, 1.91f, 0.75f, true);
    }

    void NewTerrainContentsGenerator23::generateChunkContentsPass1(TerrainChunk *chunk)
    {
        generateSurfaceParameters(chunk);
        generateTerrain(chunk);
    }
    void NewTerrainContentsGenerator23::generateChunkContentsPass2(TerrainChunk *chunk) {}
    void NewTerrainContentsGenerator23::generateChunkContentsPass3(TerrainChunk *chunk)
    {
        generateCaves(chunk);
        generatePockets(chunk);
        generateMinerals(chunk);
        generateSurface(chunk);
        propagateFluidsDownwards(chunk);
    }
    void NewTerrainContentsGenerator23::generateChunkContentsPass4(TerrainChunk *chunk)
    {
        generateGrassAndPlants(chunk);
        generateLogs(chunk);
        generateTrees(chunk);
        generateCacti(chunk);
        generatePumpkins(chunk);
        generateKelp(chunk);
        generateSeagrass(chunk);
        generateBottomSuckers(chunk);
        generateTraps(chunk);
        generateIvy(chunk);
        generateGraves(chunk);
        generateCairns(chunk);
        generateSnowAndIce(chunk);
        generateBedrockAndAir(chunk);
        updateFluidIsTop(chunk);
    }

    bool NewTerrainContentsGenerator23::canSupportSnow(int32_t value)
    {
        int32_t blockContents = Terrain::ExtractContents(value);
        Block *block = GameSingleton::blocksManager->blocks[blockContents];
        if (block->IsTransparent)
        {
            switch (blockContents)
            {
            case OakLeavesBlock::Index():
            case BirchLeavesBlock::Index():
            case MimosaLeavesBlock::Index():
            case SpruceLeavesBlock::Index():
            case TallSpruceLeavesBlock::Index():
                return true;
            default:
                return false;
            }
        }
        return true;
    }

    bool NewTerrainContentsGenerator23::bottomSuckerIsSupport(int32_t value, int32_t face)
    {
        Block *block = GameSingleton::blocksManager->blocks[Terrain::ExtractContents(value)];
        if (block->IsCollidable)
        {
            return false == block->isFaceTransparent(CellFace::OppositeFace(face), value);
        }
        return false;
    }

    // ok
    void NewTerrainContentsGenerator23::generateSurfaceParameters(TerrainChunk *chunk)
    {
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = i + chunk->origin.posX;
                int32_t num2 = j + chunk->origin.posY;
                chunk->setTemperatureFast(i, j, calculateTemperature(num, num2));
                chunk->setHumidityFast(i, j, calculateHumidity(num, num2));
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateTerrain(TerrainChunk *chunk)
    {
        int32_t num = 16;
        int32_t num2 = 16;
        int32_t num3 = chunk->origin.posX;
        int32_t num4 = chunk->origin.posY;
        Grid2d grid2d(num, num2);
        Grid2d grid2d2(num, num2);
        for (int32_t i = 0; i < num2; i++)
        {
            for (int32_t j = 0; j < num; j++)
            {
                grid2d.set(j, i, calculateOceanShoreDistance(j + num3, i + num4));
                grid2d2.set(j, i, calculateMountainRangeFactor(j + num3, i + num4));
            }
        }
        Grid3d grid3d(num / 4 + 1, 33, num2 / 4 + 1);
        for (int32_t k = 0; k < grid3d.sizeX; k++)
        {
            for (int32_t l = 0; l < grid3d.sizeZ; l++)
            {
                int32_t num5 = k * 4 + num3;
                int32_t num6 = l * 4 + num4;
                float num7 = calculateHeight(num5, num6);
                float v = calculateMountainRangeFactor(num5, num6);
                float num8 = MathUtils::Lerp(TGMinTurbulence, 1.0f, Squish(v, TGTurbulenceZero, 1.0f));
                for (int32_t m = 0; m < grid3d.sizeY; m++)
                {
                    int32_t num9 = m * 8;
                    float num10 = TGTurbulenceStrength * num8 * MathUtils::Saturate(num7 - (float)num9) * (2.0f * ScSimplexNoise::OctavedNoise(num5, num9, num6, TGTurbulenceFreq, TGTurbulenceOctaves, 4.0f, TGTurbulencePersistence) - 1.0f);
                    float num11 = (float)num9 + num10;
                    float num12 = num7 - num11;
                    num12 += MathUtils::Max(4.0f * (TGDensityBias - (float)num9), 0.0f);
                    grid3d.set(k, m, l, num12);
                }
            }
        }
        int32_t oceanLevel = getOceanLevel();
        for (int32_t n = 0; n < grid3d.sizeX - 1; n++)
        {
            for (int32_t num13 = 0; num13 < grid3d.sizeZ - 1; num13++)
            {
                for (int32_t num14 = 0; num14 < grid3d.sizeY - 1; num14++)
                {
                    float dataBuff[8];
                    grid3d.get8Value(n, num14, num13, dataBuff);
                    float v2 = dataBuff[0];
                    float v3 = dataBuff[1];
                    float v4 = dataBuff[2];
                    float v5 = dataBuff[3];
                    float v6 = dataBuff[4];
                    float v7 = dataBuff[5];
                    float v8 = dataBuff[6];
                    float v9 = dataBuff[7];

                    float num15 = (v3 - v2) / 4.0f;
                    float num16 = (v5 - v4) / 4.0f;
                    float num17 = (v7 - v6) / 4.0f;
                    float num18 = (v9 - v8) / 4.0f;
                    float num19 = v2;
                    float num20 = v4;
                    float num21 = v6;
                    float num22 = v8;
                    for (int32_t num23 = 0; num23 < 4; num23++)
                    {
                        float num24 = (num21 - num19) / 4.0f;
                        float num25 = (num22 - num20) / 4.0f;
                        float num26 = num19;
                        float num27 = num20;
                        for (int32_t num28 = 0; num28 < 4; num28++)
                        {
                            float num29 = (num27 - num26) / 8.0f;
                            float num30 = num26;
                            int32_t num31 = num23 + n * 4;
                            int32_t num32 = num28 + num13 * 4;
                            int32_t x3 = num31;
                            int32_t z3 = num32;
                            float x4 = grid2d.get(num31, num32);
                            float num33 = grid2d2.get(num31, num32);
                            int32_t temperatureFast = chunk->getTemperatureFast(x3, z3);
                            int32_t humidityFast = chunk->getHumidityFast(x3, z3);
                            float f = num33 - 0.01f * (float)humidityFast;
                            float num34 = MathUtils::Lerp(100.0f, 0.0f, f);
                            float num35 = MathUtils::Lerp(300.0f, 30.0f, f);
                            bool flag = (temperatureFast > 8 && humidityFast < 8 && num33 < 0.97f) || (MathUtils::Abs(x4) < 16.0f && num33 < 0.97f);
                            int32_t num36 = TerrainChunk::CalculateCellIndex(x3, 0, z3);
                            for (int32_t num37 = 0; num37 < 8; num37++)
                            {
                                int32_t num38 = num37 + num14 * 8;
                                int32_t value = 0;
                                if (num30 < 0.0f)
                                {
                                    if (num38 <= oceanLevel)
                                    {
                                        value = 18;
                                    }
                                }
                                else
                                {
                                    value = ((!flag) ? ((!(num30 < num35)) ? 67 : 3) : ((!(num30 < num34)) ? ((!(num30 < num35)) ? 67 : 3) : 4));
                                }
                                chunk->setCellValueFast(num36 + num38, value);
                                num30 += num29;
                            }
                            num26 += num24;
                            num27 += num25;
                        }
                        num19 += num15;
                        num20 += num16;
                        num21 += num17;
                        num22 += num18;
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateCaves(TerrainChunk *chunk)
    {
        static int32_t count = 0;
        count++;
        if (TGCavesAndPockets == false)
        {
            return;
        }
        std::vector<CavePoint> cavePointVec;
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        for (int32_t i = x - 2; i <= x + 2; i++)
        {
            for (int32_t j = y - 2; j <= y + 2; j++)
            {
                cavePointVec.clear();
                Random random(m_seed + i + 9973 * j);
                int32_t num = i * 16 + random.getInt(0, 15);
                int32_t num2 = j * 16 + random.getInt(0, 15);
                float probability = 0.5f;
                if (random.getBool(probability) == false)
                {
                    continue;
                }
                int32_t num3 = (int32_t)calculateHeight(num, num2);
                int32_t num4 = (int32_t)calculateHeight(num + 3, num2);
                int32_t num5 = (int32_t)calculateHeight(num, num2 + 3);
                Vector3 position(num, num3 - 1, num2);
                Vector3 v(3.0f, num4 - num3, 0.0f);
                Vector3 v2(0.0f, num5 - num3, 3.0f);
                Vector3 direction = Vector3::Normalize(Vector3::Cross(v, v2));
                if (direction.posY > -0.6f)
                {
                    cavePointVec.emplace_back(position, direction, 0, random.getInt(80, 240), 0);
                }
                int32_t num6 = i * 16 + 8;
                int32_t num7 = j * 16 + 8;
                int32_t num8 = 0;
                while (num8 < cavePointVec.size())
                {
                    CavePoint &cavePoint = cavePointVec[num8];
                    std::vector<TerrainBrush> &list2 = caveBrushesByType[cavePoint.brushType];
                    list2[random.getInt(0, list2.size() - 1)].paintFastAvoidWater(subsystemTerrain, chunk, Terrain::ToCell(cavePoint.position.posX), Terrain::ToCell(cavePoint.position.posY), Terrain::ToCell(cavePoint.position.posZ));
                    cavePoint.position += 2.0f * cavePoint.direction;
                    cavePoint.stepsTaken += 2;
                    float num9 = cavePoint.position.posX - (float)num6;
                    float num10 = cavePoint.position.posZ - (float)num7;
                    if (random.getBool(0.5f))
                    {
                        Vector3 vector = Vector3::Normalize(random.getVector3(1.0f));
                        if ((num9 < -25.5f && vector.posX < 0.0f) || (num9 > 25.5f && vector.posX > 0.0f))
                        {
                            vector.posX = 0.0f - vector.posX;
                        }
                        if ((num10 < -25.5f && vector.posZ < 0.0f) || (num10 > 25.5f && vector.posZ > 0.0f))
                        {
                            vector.posZ = 0.0f - vector.posZ;
                        }
                        if ((cavePoint.direction.posY < -0.5f && vector.posY < -10.0f) || (cavePoint.direction.posY > 0.1f && vector.posY > 0.0f))
                        {
                            vector.posY = 0.0f - vector.posY;
                        }
                        cavePoint.direction = Vector3::Normalize(cavePoint.direction + 0.5f * vector);
                    }
                    if (cavePoint.stepsTaken > 20 && random.getBool(0.06f))
                    {
                        cavePoint.direction = Vector3::Normalize(random.getVector3(1.0f) * Vector3(1.0f, 0.33f, 1.0f));
                    }
                    if (cavePoint.stepsTaken > 20 && random.getBool(0.05f))
                    {
                        cavePoint.direction.posY = 0.0f;
                        cavePoint.brushType = MathUtils::Min<int32_t>(cavePoint.brushType + 2, caveBrushesByType.size() - 1);
                    }
                    if (cavePoint.stepsTaken > 30 && random.getBool(0.03f))
                    {
                        cavePoint.direction.posX = 0.0f;
                        cavePoint.direction.posY = -1.0f;
                        cavePoint.direction.posZ = 0.0f;
                    }
                    if (cavePoint.stepsTaken > 30 && cavePoint.position.posY < 30.0f && random.getBool(0.02f))
                    {
                        cavePoint.direction.posX = 0.0f;
                        cavePoint.direction.posY = 1.0f;
                        cavePoint.direction.posZ = 0.0f;
                    }
                    if (random.getBool(0.33f))
                    {
                        cavePoint.brushType = (int32_t)(MathUtils::Pow(random.getFloat(0.0f, 0.999f), 7.0f) * (float)caveBrushesByType.size());
                    }
                    if (random.getBool(0.06f) && cavePointVec.size() < 12 && cavePoint.stepsTaken > 20 && cavePoint.position.posY < 58.0f)
                    {
                        cavePointVec.emplace_back(
                            cavePoint.position,
                            Vector3::Normalize(random.getVector3(1.0f, 1.0f) * Vector3(1.0f, 0.33f, 1.0f)),
                            (int32_t)(MathUtils::Pow(random.getFloat(0.0f, 0.999f), 7.0f) * (float)caveBrushesByType.size()),
                            random.getInt(40, 180),
                            0);
                    }
                    if (cavePoint.stepsTaken >= cavePoint.length || MathUtils::Abs<float>(num9) > 34.0f || MathUtils::Abs<float>(num10) > 34.0f || cavePoint.position.posY < 5.0f || cavePoint.position.posY > 246.0f)
                    {
                        num8++;
                    }
                    else if (cavePoint.stepsTaken % 20 == 0)
                    {
                        float num11 = calculateHeight(cavePoint.position.posX, cavePoint.position.posZ);
                        if (cavePoint.position.posY > num11 + 1.0f)
                        {
                            num8++;
                        }
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generatePockets(TerrainChunk *chunk)
    {
        if (TGCavesAndPockets == false)
        {
            return;
        }
        for (int32_t i = -1; i <= 1; i++)
        {
            for (int32_t j = -1; j <= 1; j++)
            {
                int32_t num = i + chunk->coords.posX;
                int32_t num2 = j + chunk->coords.posY;
                Random random(m_seed + num + 71 * num2);
                int32_t num3 = random.getInt(0, 10);
                for (int32_t k = 0; k < num3; k++)
                {
                    random.getInt(0, 1);
                }
                float num4 = calculateMountainRangeFactor(num * 16, num2 * 16);
                for (int32_t l = 0; l < 3; l++)
                {
                    int32_t x = num * 16 + random.getInt(0, 15);
                    int32_t y = random.getInt(50, 100);
                    int32_t z = num2 * 16 + random.getInt(0, 15);
                    dirtPocketBrushes[random.getInt(0, dirtPocketBrushes.size() - 1)].paintFastSelective(chunk, x, y, z, 3);
                }
                for (int32_t m = 0; m < 10; m++)
                {
                    int32_t x2 = num * 16 + random.getInt(0, 15);
                    int32_t y2 = random.getInt(20, 80);
                    int32_t z2 = num2 * 16 + random.getInt(0, 15);
                    gravelPocketBrushes[random.getInt(0, gravelPocketBrushes.size() - 1)].paintFastSelective(chunk, x2, y2, z2, 3);
                }
                for (int32_t n = 0; n < 2; n++)
                {
                    int32_t x3 = num * 16 + random.getInt(0, 15);
                    int32_t y3 = random.getInt(20, 120);
                    int32_t z3 = num2 * 16 + random.getInt(0, 15);
                    limestonePocketBrushes[random.getInt(0, limestonePocketBrushes.size() - 1)].paintFastSelective(chunk, x3, y3, z3, 3);
                }
                for (int32_t num5 = 0; num5 < 1; num5++)
                {
                    int32_t x4 = num * 16 + random.getInt(0, 15);
                    int32_t y4 = random.getInt(50, 70);
                    int32_t z4 = num2 * 16 + random.getInt(0, 15);
                    clayPocketBrushes[random.getInt(0, clayPocketBrushes.size() - 1)].paintFastSelective(chunk, x4, y4, z4, 3);
                }
                for (int32_t num6 = 0; num6 < 6; num6++)
                {
                    int32_t x5 = num * 16 + random.getInt(0, 15);
                    int32_t y5 = random.getInt(40, 80);
                    int32_t z5 = num2 * 16 + random.getInt(0, 15);
                    sandPocketBrushes[random.getInt(0, sandPocketBrushes.size() - 1)].paintFastSelective(chunk, x5, y5, z5, 4);
                }
                for (int32_t num7 = 0; num7 < 4; num7++)
                {
                    int32_t x6 = num * 16 + random.getInt(0, 15);
                    int32_t y6 = random.getInt(40, 60);
                    int32_t z6 = num2 * 16 + random.getInt(0, 15);
                    basaltPocketBrushes[random.getInt(0, basaltPocketBrushes.size() - 1)].paintFastSelective(chunk, x6, y6, z6, 4);
                }
                for (int32_t num8 = 0; num8 < 3; num8++)
                {
                    int32_t x7 = num * 16 + random.getInt(0, 15);
                    int32_t y7 = random.getInt(20, 40);
                    int32_t z7 = num2 * 16 + random.getInt(0, 15);
                    basaltPocketBrushes[random.getInt(0, basaltPocketBrushes.size() - 1)].paintFastSelective(chunk, x7, y7, z7, 3);
                }
                for (int32_t num9 = 0; num9 < 6; num9++)
                {
                    int32_t x8 = num * 16 + random.getInt(0, 15);
                    int32_t y8 = random.getInt(4, 50);
                    int32_t z8 = num2 * 16 + random.getInt(0, 15);
                    granitePocketBrushes[random.getInt(0, granitePocketBrushes.size() - 1)].paintFastSelective(chunk, x8, y8, z8, 67);
                }
                if (random.getBool(0.02f + 0.01f * num4))
                {
                    int32_t num10 = num * 16;
                    int32_t num11 = random.getInt(40, 60);
                    int32_t num12 = num2 * 16;
                    int32_t num13 = random.getInt(1, 3);
                    for (int32_t num14 = 0; num14 < num13; num14++)
                    {
                        Vector2 vector = random.getVector2(7.0f);
                        int32_t num15 = 8 + (int32_t)MathUtils::Round(vector.posX);
                        int32_t num16 = 0;
                        int32_t num17 = 8 + (int32_t)MathUtils::Round(vector.posY);
                        waterPocketBrushes[random.getInt(0, waterPocketBrushes.size() - 1)].paintFast(chunk, num10 + num15, num11 + num16, num12 + num17);
                    }
                }
                if (random.getBool(0.06f + 0.05f * num4))
                {
                    int32_t num18 = num * 16;
                    int32_t num19 = random.getInt(15, 42);
                    int32_t num20 = num2 * 16;
                    int32_t num21 = random.getInt(1, 2);
                    for (int32_t num22 = 0; num22 < num21; num22++)
                    {
                        Vector2 vector2 = random.getVector2(7.0f);
                        int32_t num23 = 8 + (int32_t)MathUtils::Round(vector2.posX);
                        int32_t num24 = random.getInt(0, 1);
                        int32_t num25 = 8 + (int32_t)MathUtils::Round(vector2.posY);
                        magmaPocketBrushes[random.getInt(0, magmaPocketBrushes.size() - 1)].paintFast(chunk, num18 + num23, num19 + num24, num20 + num25);
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateMinerals(TerrainChunk *chunk)
    {
        if (!TGCavesAndPockets)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        for (int32_t i = x - 1; i <= x + 1; i++)
        {
            for (int32_t j = y - 1; j <= y + 1; j++)
            {
                Random random(m_seed + i + 119 * j);
                int32_t num = random.getInt(0, 10);
                for (int32_t k = 0; k < num; k++)
                {
                    random.getInt(0, 1);
                }
                float num2 = calculateMountainRangeFactor(i * 16, j * 16);
                int32_t num3 = (int32_t)(5.0f + 3.0f * num2 * ScSimplexNoise::OctavedNoise(i, j, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t l = 0; l < num3; l++)
                {
                    int32_t x2 = i * 16 + random.getInt(0, 15);
                    int32_t y2 = random.getInt(5, 200);
                    int32_t z = j * 16 + random.getInt(0, 15);
                    coalBrushes[random.getInt(0, coalBrushes.size() - 1)].paintFastSelective(chunk, x2, y2, z, 3);
                }
                int32_t num4 = (int32_t)(6.0f + 2.0f * num2 * ScSimplexNoise::OctavedNoise(i + 1211, j + 396, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t m = 0; m < num4; m++)
                {
                    int32_t x3 = i * 16 + random.getInt(0, 15);
                    int32_t y3 = random.getInt(20, 65);
                    int32_t z2 = j * 16 + random.getInt(0, 15);
                    copperBrushes[random.getInt(0, copperBrushes.size() - 1)].paintFastSelective(chunk, x3, y3, z2, 3);
                }
                int32_t num5 = (int32_t)(5.0f + 2.0f * num2 * ScSimplexNoise::OctavedNoise(i + 713, j + 211, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t n = 0; n < num5; n++)
                {
                    int32_t x4 = i * 16 + random.getInt(0, 15);
                    int32_t y4 = random.getInt(2, 40);
                    int32_t z3 = j * 16 + random.getInt(0, 15);
                    ironBrushes[random.getInt(0, ironBrushes.size() - 1)].paintFastSelective(chunk, x4, y4, z3, 67);
                }
                int32_t num6 = (int32_t)(3.0f + 3.0f * num2 * ScSimplexNoise::OctavedNoise(i + 915, j + 272, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t num7 = 0; num7 < num6; num7++)
                {
                    int32_t x5 = i * 16 + random.getInt(0, 15);
                    int32_t y5 = random.getInt(50, 90);
                    int32_t z4 = j * 16 + random.getInt(0, 15);
                    saltpeterBrushes[random.getInt(0, saltpeterBrushes.size() - 1)].paintFastSelective(chunk, x5, y5, z4, 4);
                }
                int32_t num8 = (int32_t)(3.0f + 2.0f * num2 * ScSimplexNoise::OctavedNoise(i + 711, j + 1194, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t num9 = 0; num9 < num8; num9++)
                {
                    int32_t x6 = i * 16 + random.getInt(0, 15);
                    int32_t y6 = random.getInt(2, 40);
                    int32_t z5 = j * 16 + random.getInt(0, 15);
                    sulphurBrushes[random.getInt(0, sulphurBrushes.size() - 1)].paintFastSelective(chunk, x6, y6, z5, 67);
                }
                int32_t num10 = (int32_t)(0.5f + 2.0f * num2 * ScSimplexNoise::OctavedNoise(i + 432, j + 907, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t num11 = 0; num11 < num10; num11++)
                {
                    int32_t x7 = i * 16 + random.getInt(0, 15);
                    int32_t y7 = random.getInt(2, 15);
                    int32_t z6 = j * 16 + random.getInt(0, 15);
                    diamondBrushes[random.getInt(0, diamondBrushes.size() - 1)].paintFastSelective(chunk, x7, y7, z6, 67);
                }
                int32_t num12 = (int32_t)(3.0f + 2.0f * num2 * ScSimplexNoise::OctavedNoise(i + 799, j + 131, 0.33f, 1, 1.0f, 1.0f));
                for (int32_t num13 = 0; num13 < num12; num13++)
                {
                    int32_t x8 = i * 16 + random.getInt(0, 15);
                    int32_t y8 = random.getInt(2, 50);
                    int32_t z7 = j * 16 + random.getInt(0, 15);
                    germaniumBrushes[random.getInt(0, germaniumBrushes.size() - 1)].paintFastSelective(chunk, x8, y8, z7, 67);
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateSurface(TerrainChunk *chunk)
    {
        Random random(m_seed + chunk->coords.posX + 101 * chunk->coords.posY);
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = i + chunk->origin.posX;
                int32_t num2 = j + chunk->origin.posY;
                int32_t num3 = TerrainChunk::CalculateCellIndex(i, 254, j);
                int32_t num4 = 254;
                while (num4 >= 0)
                {
                    int32_t num5 = Terrain::ExtractContents(chunk->getCellValueFast(num3));
                    if (false == GameSingleton::blocksManager->blocks[num5]->IsTransparent)
                    {
                        float num6 = calculateMountainRangeFactor(num, num2);
                        int32_t temperature = chunk->getTemperatureFast(i, j); // subsystemTerrain->getTemperature(num, num2);
                        int32_t humidity = chunk->getHumidityFast(i, j);
                        int32_t num7;
                        if (num5 == 4)
                        {
                            num7 = ((temperature > 4 && temperature < 7) ? 6 : 7);
                        }
                        else
                        {
                            int32_t num8 = temperature / 4;
                            int32_t num9 = ((num4 + 1 < 255) ? chunk->getCellContentsFast(i, num4 + 1, j) : 0);
                            // 冰的高度
                            num7 = ((num4 > 150 && SubsystemWeather::IsPlaceFrozen(temperature, num4)) ? 62 : (((num4 < 66 || num4 == 84 + num8 || num4 == 103 + num8) && humidity == 9 && temperature % 6 == 1) ? 66 : ((num9 != 18 || humidity <= 8 || humidity % 2 != 0 || temperature % 3 != 0) ? 2 : 72)));
                        }
                        int32_t num10;
                        if (num7 == 62)
                        {
                            num10 = (int32_t)MathUtils::Clamp(1.0f * (float)(-temperature), 1.0f, 7.0f);
                        }
                        else
                        {
                            // 泥土覆盖的高度
                            float num11 = MathUtils::Saturate(((float)num4 - 120.0f) * 0.05f);
                            float f = MathUtils::Saturate(MathUtils::Saturate((num6 - 0.9f) / 0.1f) - MathUtils::Saturate(((float)humidity - 3.0f) / 12.0f) + TGSurfaceMultiplier * num11);
                            int32_t min = (int32_t)MathUtils::Lerp(4.0f, 0.0f, f);
                            int32_t max = (int32_t)MathUtils::Lerp(7.0f, 0.0f, f);
                            num10 = MathUtils::Min(random.getInt(min, max), num4);
                        }
                        int32_t num12 = TerrainChunk::CalculateCellIndex(i, num4 + 1, j);
                        for (int32_t k = num12 - num10; k < num12; k++)
                        {
                            if (Terrain::ExtractContents(chunk->getCellValueFast(k)) != 0)
                            {
                                int32_t value = Terrain::ReplaceContents(0, num7);
                                chunk->setCellValueFast(k, value);
                            }
                        }
                        break;
                    }
                    num4--;
                    num3--;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::propagateFluidsDownwards(TerrainChunk *chunk)
    {
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = TerrainChunk::CalculateCellIndex(i, 255, j);
                int32_t num2 = 0;
                int32_t num3 = 255;
                while (num3 >= 0)
                {
                    int32_t num4 = Terrain::ExtractContents(chunk->getCellValueFast(num));
                    if (num4 == 0 && num2 != 0 && GameSingleton::blocksManager->blocks[num2]->isBlock<FluidBlock *>() == true)
                    {
                        chunk->setCellValueFast(num, num2);
                        num4 = num2;
                    }
                    num2 = num4;
                    num3--;
                    num--;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateGrassAndPlants(TerrainChunk *chunk)
    {
        if (TGExtras == false)
        {
            return;
        }
        Random random(m_seed + chunk->coords.posX + 3943 * chunk->coords.posY);
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                for (int32_t num = 254; num >= 0; num--)
                {
                    int32_t cellValueFast = chunk->getCellValueFast(i, num, j);
                    int32_t num2 = Terrain::ExtractContents(cellValueFast);
                    if (num2 != 0)
                    {
                        if (GameSingleton::blocksManager->blocks[num2]->isBlock<FluidBlock *>() == false)
                        {
                            int32_t temperatureFast = chunk->getTemperatureFast(i, j);
                            int32_t humidityFast = chunk->getHumidityFast(i, j);
                            int32_t num3 = GameSingleton::plantsManager->generateRandomPlantValue(random, cellValueFast, temperatureFast, humidityFast, num + 1);
                            if (num3 != 0)
                            {
                                chunk->setCellValueFast(i, num + 1, j, num3);
                            }
                            if (num2 == 2)
                            {
                                chunk->setCellValueFast(i, num, j, Terrain::MakeBlockValue(8, 0, 0));
                            }
                        }
                        break;
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateLogs(TerrainChunk *chunk)
    {
        if (false == TGExtras)
        {
            return;
        }
        int32_t x = chunk->origin.posX;
        int32_t num = x + 16;
        int32_t y = chunk->origin.posY;
        int32_t num2 = y + 16;

        Random random(m_seed + chunk->coords.posX + 3943 * chunk->coords.posY);
        int32_t humidity = calculateHumidity(chunk->coords.posX * 16, chunk->coords.posY * 16);
        int32_t num3 = calculateTemperature(chunk->coords.posX * 16, chunk->coords.posY * 16);
        float num4 = MathUtils::Saturate((ScSimplexNoise::OctavedNoise(chunk->coords.posX, chunk->coords.posY, 0.1f, 2, 2.0f, 0.5f) - 0.25f) / 0.2f + (random.getBool(0.25f) ? 0.5f : 0.0f));
        int32_t num5 = 0;
        if (num4 > 0.9f)
        {
            num5 = random.getInt(1, 2);
        }
        else if (num4 > 0.6f)
        {
            num5 = random.getInt(0, 1);
        }
        int32_t num6 = 0;
        for (int32_t k = 0; k < 12; k++)
        {
            if (num6 >= num5)
            {
                break;
            }
            int32_t num7 = chunk->coords.posX * 16 + random.getInt(0, 15);
            int32_t num8 = chunk->coords.posY * 16 + random.getInt(0, 15);
            int32_t num9 = subsystemTerrain->calculateTopmostCellHeight(num7, num8);
            if (num9 < 66)
            {
                continue;
            }
            int32_t cellContentsFast = subsystemTerrain->getCellContents(num7, num9, num8);
            if (cellContentsFast != 2 && cellContentsFast != 8)
            {
                continue;
            }
            num9++;
            int32_t num10 = random.getInt(3, 7);
            Point3 point = CellFace::FaceToPoint3(random.getInt(0, 3));
            if (point.posX < 0 && num7 - num10 + 1 < 0)
            {
                point.posX *= -1;
            }
            if (point.posX > 0 && num7 + num10 - 1 > 15)
            {
                point.posX *= -1;
            }
            if (point.posZ < 0 && num8 - num10 + 1 < 0)
            {
                point.posZ *= -1;
            }
            if (point.posZ > 0 && num8 + num10 - 1 > 15)
            {
                point.posZ *= -1;
            }
            bool flag = true;
            bool flag2 = false;
            bool flag3 = false;
            for (int32_t l = 0; l < num10; l++)
            {
                int32_t num11 = num7 + point.posX * l;
                int32_t num12 = num8 + point.posZ * l;
                if (num11 < x + 1 || num11 >= num - 1 || num12 < y + 1 || num12 >= num2 - 1)
                {
                    flag = false;
                    break;
                }
                if (GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num11, num9, num12)]->IsCollidable)
                {
                    flag = false;
                    break;
                }
                if (GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num11, num9 - 1, num12)]->IsCollidable)
                {
                    if (l <= MathUtils::Max(num10 / 2, 0))
                    {
                        flag2 = true;
                    }
                    if (l >= MathUtils::Min(num10 / 2 + 1, num10 - 1))
                    {
                        flag3 = true;
                    }
                }
            }
            if (!(flag && flag2 && flag3))
            {
                continue;
            }
            Point3 point2 = ((point.posX != 0) ? Point3(0, 0, 1) : Point3(1, 0, 0));
            TreeType treeType = GameSingleton::plantsManager->generateRandomTreeType(random, num3 + SubsystemWeather::GetTemperatureAdjustmentAtHeight(num9), humidity, num9, 2.0f);
            if (treeType != TreeType::None)
            {
                int32_t treeTrunkValue = GameSingleton::plantsManager->getTreeTrunkValue(treeType);
                treeTrunkValue = Terrain::ReplaceData(treeTrunkValue, WoodBlock::SetCutFace(Terrain::ExtractData(treeTrunkValue), (point.posX != 0) ? 1 : 0));
                int32_t treeLeavesValue = GameSingleton::plantsManager->getTreeLeavesValue(treeType);
                for (int32_t m = 0; m < num10; m++)
                {
                    int32_t num13 = num7 + point.posX * m;
                    int32_t num14 = num8 + point.posZ * m;
                    subsystemTerrain->setCellValue(num13, num9, num14, treeTrunkValue);
                    if (m > num10 / 2)
                    {
                        if (random.getBool(0.5f) && false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num13 + point2.posX, num9, num14 + point2.posZ)]->IsCollidable)
                        {
                            subsystemTerrain->setCellValue(num13 + point2.posX, num9, num14 + point2.posZ, treeLeavesValue);
                        }
                        if (random.getBool(0.05f) && false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num13 + point2.posX, num9, num14 + point2.posZ)]->IsCollidable)
                        {
                            subsystemTerrain->setCellValue(num13 + point2.posX, num9, num14 + point2.posZ, treeTrunkValue);
                        }
                        if (random.getBool(0.5f) && false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num13 - point2.posX, num9, num14 - point2.posZ)]->IsCollidable)
                        {
                            subsystemTerrain->setCellValue(num13 - point2.posX, num9, num14 - point2.posZ, treeLeavesValue);
                        }
                        if (random.getBool(0.05f) && false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num13 - point2.posX, num9, num14 - point2.posZ)]->IsCollidable)
                        {
                            subsystemTerrain->setCellValue(num13 - point2.posX, num9, num14 - point2.posZ, treeTrunkValue);
                        }
                        if (random.getBool(0.5f) && false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num13, num9 + 1, num14)]->IsCollidable)
                        {
                            subsystemTerrain->setCellValue(num13, num9 + 1, num14, treeLeavesValue);
                        }
                    }
                }
            }
            num6++;
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateTrees(TerrainChunk *chunk)
    {
        if (false == TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        for (int32_t i = x; i <= x; i++)
        {
            for (int32_t j = y; j <= y; j++)
            {
                Random random(m_seed + i + 3943 * j);
                int32_t humidity = calculateHumidity(i * 16, j * 16);
                int32_t num = calculateTemperature(i * 16, j * 16);
                float num2 = MathUtils::Saturate((ScSimplexNoise::OctavedNoise(i, j, 0.1f, 2, 2.0f, 0.5f) - 0.25f) / 0.2f + (random.getBool(0.25f) ? 0.5f : 0.0f));
                int32_t num3 = (int32_t)(5.0f * num2);
                int32_t num4 = 0;
                for (int32_t k = 0; k < 32; k++)
                {
                    if (num4 >= num3)
                    {
                        break;
                    }
                    int32_t num5 = i * 16 + random.getInt(2, 13);
                    int32_t num6 = j * 16 + random.getInt(2, 13);
                    int32_t num7 = subsystemTerrain->calculateTopmostCellHeight(num5, num6);
                    if (num7 < 66)
                    {
                        continue;
                    }
                    int32_t cellContentsFast = subsystemTerrain->getCellContents(num5, num7, num6);
                    if (cellContentsFast != 2 && cellContentsFast != 8)
                    {
                        continue;
                    }
                    num7++;
                    if (false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num5 + 1, num7, num6)]->IsCollidable &&
                        false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num5 - 1, num7, num6)]->IsCollidable &&
                        false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num5, num7, num6 + 1)]->IsCollidable &&
                        false == GameSingleton::blocksManager->blocks[subsystemTerrain->getCellContents(num5, num7, num6 - 1)]->IsCollidable)
                    {
                        TreeType treeType = GameSingleton::plantsManager->generateRandomTreeType(random, num + SubsystemWeather::GetTemperatureAdjustmentAtHeight(num7), humidity, num7);
                        
                        if (treeType != TreeType::None)
                        {
                            std::vector<TerrainBrush> &treeBrushes = GameSingleton::plantsManager->getTreeBrushes(treeType);
                            TerrainBrush &terrainBrush = treeBrushes[random.getInt(treeBrushes.size())];
                            terrainBrush.paintFast(chunk, num5, num7, num6);
                        }
                        num4++;
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateCacti(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random(m_seed + x + 1991 * y);
        if (!random.getBool(0.5f))
        {
            return;
        }
        int32_t num = random.getInt(0, MathUtils::Max(1, 1));
        for (int32_t i = 0; i < num; i++)
        {
            int32_t num2 = random.getInt(3, 12);
            int32_t num3 = random.getInt(3, 12);
            int32_t humidityFast = chunk->getHumidityFast(num2, num3);
            int32_t temperatureFast = chunk->getTemperatureFast(num2, num3);
            if (humidityFast >= 6 || temperatureFast <= 8)
            {
                continue;
            }
            for (int32_t j = 0; j < 8; j++)
            {
                int32_t num4 = num2 + random.getInt(-2, 2);
                int32_t num5 = num3 + random.getInt(-2, 2);
                for (int32_t num6 = 251; num6 >= 0; num6--)
                {
                    switch (Terrain::ExtractContents(chunk->getCellValueFast(num4, num6, num5)))
                    {
                    case 7:
                    {
                        for (int32_t k = num6 + 1; k <= num6 + 3 &&
                                                   chunk->getCellContentsFast(num4 + 1, k, num5) == 0 &&
                                                   chunk->getCellContentsFast(num4 - 1, k, num5) == 0 &&
                                                   chunk->getCellContentsFast(num4, k, num5 + 1) == 0 &&
                                                   chunk->getCellContentsFast(num4, k, num5 - 1) == 0;
                             k++)
                        {
                            chunk->setCellValueFast(num4, k, num5, Terrain::MakeBlockValue(127));
                        }
                        break;
                    }
                    case 0:
                        continue;
                    }
                    break;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generatePumpkins(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random(m_seed + x + 1495 * y);
        if (!random.getBool(0.2f))
        {
            return;
        }
        int32_t num = random.getInt(0, MathUtils::Max(1, 1));
        for (int32_t i = 0; i < num; i++)
        {
            int32_t num2 = random.getInt(1, 14);
            int32_t num3 = random.getInt(1, 14);
            int32_t humidityFast = chunk->getHumidityFast(num2, num3);
            int32_t temperatureFast = chunk->getTemperatureFast(num2, num3);
            if (humidityFast < 10 || temperatureFast <= 6)
            {
                continue;
            }
            for (int32_t j = 0; j < 5; j++)
            {
                int32_t x2 = num2 + random.getInt(-1, 1);
                int32_t z = num3 + random.getInt(-1, 1);
                for (int32_t num4 = 254; num4 >= 0; num4--)
                {
                    switch (Terrain::ExtractContents(chunk->getCellValueFast(x2, num4, z)))
                    {
                    case 8:
                        chunk->setCellValueFast(x2, num4 + 1, z, random.getBool(0.25f) ? Terrain::MakeBlockValue(244) : Terrain::MakeBlockValue(131));
                        break;
                    case 0:
                        continue;
                    }
                    break;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateKelp(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random(0);
        float num = 0.0f;
        for (int32_t i = 0; i < 9; i++)
        {
            int32_t num2 = i % 3 - 1;
            int32_t num3 = i / 3 - 1;
            random.seed(m_seed + (x + num2) + 850 * (y + num3));
            if (random.getBool(0.2f))
            {
                num = MathUtils::Max(num, 0.025f);
                if (i == 4)
                {
                    num = MathUtils::Max(num, 0.1f);
                }
            }
        }
        if (num == 0.0f)
        {
            return;
        }
        random.seed(m_seed + x + 850 * y);
        int32_t num4 = random.getInt(0, MathUtils::Max((int32_t)(256.0f * num), 1));
        for (int32_t j = 0; j < num4; j++)
        {
            int32_t num5 = random.getInt(2, 13);
            int32_t num6 = random.getInt(2, 13);
            int32_t num7 = num5 + chunk->origin.posX;
            int32_t num8 = num6 + chunk->origin.posY;
            int32_t num9 = random.getInt(10, 26);
            int32_t num10 = 6;
            bool flag = true;
            if (calculateOceanShoreDistance(num7, num8) > 5.0f)
            {
                num10 = 4;
                flag = false;
            }
            if (num9 <= 0)
            {
                continue;
            }
            for (int32_t k = 0; k < num9; k++)
            {
                int32_t x2 = num5 + random.getInt(-2, 2);
                int32_t z = num6 + random.getInt(-2, 2);
                int32_t num11 = 0;
                for (int32_t num12 = 254; num12 >= 0; num12--)
                {
                    int32_t num13 = Terrain::ExtractContents(chunk->getCellValueFast(x2, num12, z));
                    Block *block = GameSingleton::blocksManager->blocks[num13];
                    if (num13 != 0)
                    {
                        if (block->isBlock<WaterBlock *>() == false)
                        {
                            if ((num13 == 2 || num13 == 7 || num13 == 72) && num11 >= 2)
                            {
                                int32_t num14 = (flag ? random.getInt(num11 - 2, num11 - 1) : random.getInt(num11 - 1, num11));
                                for (int32_t l = 0; l < num14; l++)
                                {
                                    chunk->setCellValueFast(x2, num12 + 1 + l, z, Terrain::MakeBlockValue(232));
                                }
                            }
                            break;
                        }
                        num11++;
                        if (num11 > num10)
                        {
                            break;
                        }
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateSeagrass(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random(m_seed + x + 378 * y);
        for (int32_t i = 0; i < 6; i++)
        {
            int32_t num = random.getInt(1, 14);
            int32_t num2 = random.getInt(1, 14);
            int32_t num3 = chunk->origin.posX + num;
            int32_t num4 = chunk->origin.posY + num2;
            bool flag = calculateOceanShoreDistance(num3, num4) < 10.0f;
            int32_t num5 = random.getInt(1, 3);
            for (int32_t j = 0; j < num5; j++)
            {
                int32_t x2 = num + random.getInt(-1, 1);
                int32_t z = num2 + random.getInt(-1, 1);
                int32_t num6 = 0;
                for (int32_t num7 = 254; num7 >= 0; num7--)
                {
                    int32_t num8 = Terrain::ExtractContents(chunk->getCellValueFast(x2, num7, z));
                    switch (num8)
                    {
                    case 0:
                        continue;
                    case 18:
                        num6++;
                        if (num6 <= 16)
                        {
                            continue;
                        }
                        break;
                    default:
                        if (num6 > 1 && (num8 == 2 || num8 == 7 || num8 == 72 || num8 == 3))
                        {
                            int32_t x3 = ((!random.getBool(0.1f)) ? 1 : 2);
                            x3 = (flag ? MathUtils::Min(x3, num6 - 1) : MathUtils::Min(x3, num6));
                            for (int32_t k = 0; k < x3; k++)
                            {
                                chunk->setCellValueFast(x2, num7 + 1 + k, z, Terrain::MakeBlockValue(233));
                            }
                        }
                        break;
                    }
                    break;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateBottomSuckers(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        Random random(m_seed + chunk->coords.posX + 2210 * chunk->coords.posY);
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                if (false == random.getBool(0.2f))
                {
                    continue;
                }
                int32_t num = chunk->origin.posX + i;
                int32_t num2 = chunk->origin.posY + j;
                int32_t temperatureFast = chunk->getTemperatureFast(i, j);
                if (calculateOceanShoreDistance(num, num2) > 10.0f)
                {
                    continue;
                }
                int32_t num3 = 0;
                for (int32_t num4 = 254; num4 >= 0; num4--)
                {
                    if (Terrain::ExtractContents(chunk->getCellValueFast(i, num4, j)) == 18)
                    {
                        num3++;
                        int32_t face = random.getInt(0, 5);
                        Point3 point = CellFace::FaceToPoint3(face);
                        if (i + point.posX >= 0 && i + point.posX < 16 && num4 + point.posY >= 0 && num4 + point.posY < 254 && j + point.posZ >= 0 && j + point.posZ < 16)
                        {
                            int32_t cellValueFast = chunk->getCellValueFast(i + point.posX, num4 + point.posY, j + point.posZ);
                            if (bottomSuckerIsSupport(cellValueFast, CellFace::OppositeFace(face)))
                            {
                                int32_t num5 = 0;
                                float num6 = 0.6f;
                                float num7 = 0.4f;
                                if (temperatureFast < 8)
                                {
                                    num6 = 0.9f;
                                    num7 = 0.1f;
                                }
                                if (num3 > 6)
                                {
                                    num6 *= 0.25f;
                                }
                                if (num3 > 12)
                                {
                                    num7 *= 0.5f;
                                }
                                if (num3 < 4)
                                {
                                    num7 *= 0.5f;
                                }
                                if (num4 < 45)
                                {
                                    num6 *= 0.1f;
                                    num7 *= 0.1f;
                                }
                                float num8 = random.getFloat(0.0f, 1.0f);
                                num8 -= num6;
                                if (num5 == 0 && num8 < 0.0f)
                                {
                                    num5 = 226;
                                }
                                num8 -= num7;
                                if (num5 == 0 && num8 < 0.0f)
                                {
                                    num5 = 229;
                                }
                                if (num5 != 0)
                                {
                                    int32_t face2 = random.getInt(0, 3);
                                    int32_t data = BottomSuckerBlock::SetFace(BottomSuckerBlock::SetSubvariant(0, face2), CellFace::OppositeFace(face));
                                    int32_t value = Terrain::MakeBlockValue(num5, 0, data);
                                    chunk->setCellValueFast(i, num4, j, value);
                                }
                            }
                        }
                    }
                    else
                    {
                        num3 = 0;
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateTraps(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random(m_seed + x + 2113 * y);
        if (false == random.getBool(0.15f) || false == (calculateOceanShoreDistance(chunk->origin.posX, chunk->origin.posY) > 50.0f))
        {
            return;
        }
        int32_t num = random.getInt(0, MathUtils::Max(2, 1));
        for (int32_t i = 0; i < num; i++)
        {
            int32_t num2 = random.getInt(2, 5);
            int32_t num3 = random.getInt(2, 5);
            int32_t num4 = random.getInt(1, 16 - num2 - 2);
            int32_t num5 = random.getInt(1, 16 - num3 - 2);
            bool flag = random.getFloat(0.0f, 1.0f) < 0.5f;
            int32_t num6 = random.getInt(3, 5);
            int32_t num7 = -1;
            int32_t num8 = num4 - 1;
            while (true)
            {
                if (num8 < num4 + num2 + 1)
                {
                    for (int32_t j = num5 - 1; j < num5 + num3 + 1; j++)
                    {
                        int32_t num9 = chunk->calculateTopmostCellHeight(num8, j);
                        int32_t num10 = MathUtils::Max(num9 - 20, 5);
                        while (num9 >= num10 && chunk->getCellContentsFast(num8, num9, j) != 8)
                        {
                            num9--;
                        }
                        if (num7 != -1 && num7 != num9)
                        {
                            goto end_IL_01a0;
                        }
                        num7 = num9;
                        if (chunk->getCellContentsFast(num8, num9, j) != 8)
                        {
                            goto end_IL_01a0;
                        }
                    }
                    num8++;
                    continue;
                }
                if (num7 == -1 || num7 - num6 < 5)
                {
                    break;
                }
                for (int32_t k = num4; k < num4 + num2; k++)
                {
                    for (int32_t l = num5; l < num5 + num3; l++)
                    {
                        for (int32_t num11 = num7 - 1; num11 >= num7 - num6 + 1; num11--)
                        {
                            chunk->setCellValueFast(k, num11, l, Terrain::MakeBlockValue(0));
                        }
                        chunk->setCellValueFast(k, num7, l, Terrain::MakeBlockValue(87));
                        if (flag)
                        {
                            int32_t data = SpikedPlankBlock::SetSpikesState(0, random.getFloat(0.0f, 1.0f) < 0.33f);
                            chunk->setCellValueFast(k, num7 - num6 + 1, l, Terrain::MakeBlockValue(86, 0, data));
                        }
                    }
                }
                break;
            end_IL_01a0:
                break;
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateIvy(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        Random random(m_seed + chunk->coords.posX + 2191 * chunk->coords.posY);
        int32_t num = random.getInt(0, MathUtils::Max(12, 1));
        for (int32_t i = 0; i < num; i++)
        {
            int32_t num2 = random.getInt(4, 11);
            int32_t num3 = random.getInt(4, 11);
            int32_t humidityFast = chunk->getHumidityFast(num2, num3);
            int32_t temperatureFast = chunk->getTemperatureFast(num2, num3);
            if (humidityFast < 10 || temperatureFast < 10)
            {
                continue;
            }
            int32_t num4 = chunk->calculateTopmostCellHeight(num2, num3);
            for (int32_t j = 0; j < 100; j++)
            {
                int32_t num5 = num2 + random.getInt(-3, 3);
                int32_t num6 = MathUtils::Clamp(num4 + random.getInt(-12, 1), 1, 255);
                int32_t num7 = num3 + random.getInt(-3, 3);
                switch (Terrain::ExtractContents(chunk->getCellValueFast(num5, num6, num7)))
                {
                case 2:
                case 3:
                case 8:
                case 9:
                case 12:
                case 66:
                case 67:
                {
                    int32_t num8 = random.getInt(0, 3);
                    for (int32_t k = 0; k < 4; k++)
                    {
                        int32_t face = (k + num8) % 4;
                        Point3 point = CellFace::FaceToPoint3(face);
                        if (chunk->getCellContentsFast(num5 + point.posX, num6, num7 + point.posZ) != 0)
                        {
                            continue;
                        }
                        int32_t num9 = num6 - 1;
                        while (num9 >= 1 && chunk->getCellContentsFast(num5 + point.posX, num9, num7 + point.posZ) == 0 && chunk->getCellContentsFast(num5, num9, num7) != 0)
                        {
                            num9--;
                        }
                        if (chunk->getCellContentsFast(num5 + point.posX, num9, num7 + point.posZ) != 0)
                        {
                            break;
                        }
                        num9++;
                        int32_t value = Terrain::MakeBlockValue(197, 0, IvyBlock::SetFace(0, CellFace::OppositeFace(face)));
                        while (num9 >= 1 && chunk->getCellContentsFast(num5 + point.posX, num9, num7 + point.posZ) == 0)
                        {
                            chunk->setCellValueFast(num5 + point.posX, num9, num7 + point.posZ, value);
                            if (IvyBlock::IsGrowthStopCell(num5 + point.posX, num9, num7 + point.posZ))
                            {
                                break;
                            }
                            num9--;
                        }
                        break;
                    }
                    break;
                }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateGraves(TerrainChunk *chunk)
    {
        if (!TGExtras)
        {
            return;
        }
        int32_t num15;
        int32_t data;
        int32_t num16;
        int32_t contents;
        int32_t contents2;
        bool flag2;
        float num17;
        float num18;
        int32_t num19;
        int32_t num20;
        int32_t num21;

        int32_t x = chunk->coords.posX;
        int32_t y = chunk->coords.posY;
        Random random((int32_t)MathUtils::Hash((uint32_t)(m_seed + x + 10323 * y)));
        if (!(random.getFloat(0.0f, 1.0f) < 0.033f) || false == (calculateOceanShoreDistance(chunk->origin.posX, chunk->origin.posY) > 10.0f))
        {
            return;
        }
        int32_t num = random.getInt(0, MathUtils::Max(1, 1));
        for (int32_t i = 0; i < num; i++)
        {
            int32_t num2 = random.getInt(6, 9);
            int32_t num3 = random.getInt(6, 9);
            int32_t num4 = (random.getBool(0.2f) ? random.getInt(6, 20) : random.getInt(1, 5));
            bool flag = random.getBool(0.5f);
            for (int32_t j = 0; j < num4; j++)
            {
                int32_t num5 = num2 + random.getInt(-4, 4);
                int32_t num6 = num3 + random.getInt(-4, 4);
                int32_t num7 = chunk->calculateTopmostCellHeight(num5, num6);
                if (num7 < 10 || num7 > 246)
                {
                    continue;
                }
                int32_t num8 = random.getInt(0, 3);
                for (int32_t k = 0; k < 4; k++)
                {
                    int32_t num9 = (k + num8) % 4;
                    Point3 p = CellFace::FaceToPoint3(num9);
                    Point3 p2(-p.posZ, p.posY, p.posX);
                    int32_t num10 = ((p.posX < 0) ? (num5 - 2) : (num5 - 1));
                    int32_t num11 = ((p.posX > 0) ? (num5 + 2) : (num5 + 1));
                    int32_t num12 = ((p.posZ < 0) ? (num6 - 2) : (num6 - 1));
                    int32_t num13 = ((p.posZ > 0) ? (num6 + 2) : (num6 + 1));
                    for (int32_t l = num10; l <= num11; l++)
                    {
                        for (int32_t m = num7 - 2; m <= num7 + 2; m++)
                        {
                            for (int32_t n = num12; n <= num13; n++)
                            {
                                int32_t num14 = Terrain::ExtractContents(chunk->getCellValueFast(l, m, n));
                                Block *block = GameSingleton::blocksManager->blocks[num14];
                                if (m > num7)
                                {
                                    if (false == block->IsCollidable)
                                    {
                                        continue;
                                    }
                                }
                                else if (num14 == 8 || num14 == 2 || num14 == 7 || num14 == 3 || num14 == 4)
                                {
                                    continue;
                                }
                                goto IL_06ac;
                            }
                        }
                    }
                    num15 = random.getInt(0, 7);
                    data = GravestoneBlock::SetVariant(GravestoneBlock::SetRotation(0, num9 % 2), num15);
                    num16 = -1;
                    contents = 217;
                    contents2 = 136;
                    if (num15 >= 4 && !flag)
                    {
                        int32_t cellContentsFast = chunk->getCellContentsFast(num5, num7, num6);
                        if (cellContentsFast == 7 || cellContentsFast == 4)
                        {
                            num16 = Terrain::MakeBlockValue(4);
                            contents = 51;
                            contents2 = 52;
                        }
                        else if (random.getFloat(0.0f, 1.0f) < 0.5f)
                        {
                            num16 = Terrain::MakeBlockValue(3);
                            contents = 217;
                            contents2 = 136;
                        }
                        else
                        {
                            num16 = Terrain::MakeBlockValue(67);
                            contents = 96;
                            contents2 = 95;
                        }
                    }
                    flag2 = num16 != -1 && random.getBool(0.33f);
                    num17 = random.getFloat(0.0f, 1.0f);
                    num18 = random.getFloat(0.0f, 1.0f);
                    num19 = random.getInt(-1, 0);
                    num20 = random.getInt(1, 2);
                    num21 = (flag2 ? (num7 + 2) : (num7 + 1));
                    chunk->setCellValueFast(num5, num21, num6, Terrain::MakeBlockValue(189, 0, data));
                    for (int32_t num22 = num19; num22 <= num20; num22++)
                    {
                        int32_t num23 = num5 + p.posX * num22;
                        int32_t num24 = num6 + p.posZ * num22;
                        if (num22 == 0 || num22 == 1)
                        {
                            chunk->setCellValueFast(num23, num21 - 2, num24, Terrain::MakeBlockValue(190));
                            if (num16 != -1)
                            {
                                chunk->setCellValueFast(num23, num21 - 1, num24, num16);
                                if (num22 == 1)
                                {
                                    int32_t num25 = 0;
                                    if (num18 < 0.2f)
                                    {
                                        num25 = Terrain::MakeBlockValue(20);
                                    }
                                    else if (num18 < 0.3f)
                                    {
                                        num25 = Terrain::MakeBlockValue(24);
                                    }
                                    else if (num18 < 0.4f)
                                    {
                                        num25 = Terrain::MakeBlockValue(25);
                                    }
                                    else if (num18 < 0.5f)
                                    {
                                        num25 = Terrain::MakeBlockValue(31, 0, 4);
                                    }
                                    else if (num18 < 0.6f)
                                    {
                                        num25 = Terrain::MakeBlockValue(132, 0, CellFace::OppositeFace(num9));
                                    }
                                    if (num25 != 0)
                                    {
                                        chunk->setCellValueFast(num23, num21, num24, num25);
                                    }
                                }
                            }
                        }
                        if (!flag2)
                        {
                            continue;
                        }
                        if (num17 < 0.3f)
                        {
                            int32_t value = Terrain::MakeBlockValue(contents, 0, StairsBlock::SetRotation(0, CellFace::Point3ToFace(p2)));
                            int32_t value2 = Terrain::MakeBlockValue(contents, 0, StairsBlock::SetRotation(0, CellFace::OppositeFace(CellFace::Point3ToFace(p2))));
                            chunk->setCellValueFast(num23 + p2.posX, num21 - 1, num24 + p2.posZ, value);
                            chunk->setCellValueFast(num23 - p2.posX, num21 - 1, num24 - p2.posZ, value2);
                            if (num22 == -1)
                            {
                                int32_t value3 = Terrain::MakeBlockValue(contents, 0, StairsBlock::SetRotation(0, CellFace::OppositeFace(CellFace::Point3ToFace(p))));
                                chunk->setCellValueFast(num23, num21 - 1, num24, value3);
                            }
                            if (num22 == 2)
                            {
                                int32_t value4 = Terrain::MakeBlockValue(contents, 0, StairsBlock::SetRotation(0, CellFace::Point3ToFace(p)));
                                chunk->setCellValueFast(num23, num21 - 1, num24, value4);
                            }
                        }
                        else if (num17 < 0.4f)
                        {
                            chunk->setCellValueFast(num23 + p2.posX, num21 - 1, num24 + p2.posZ, Terrain::MakeBlockValue(contents2));
                            chunk->setCellValueFast(num23 - p2.posX, num21 - 1, num24 - p2.posZ, Terrain::MakeBlockValue(contents2));
                            if (num22 == -1)
                            {
                                chunk->setCellValueFast(num23, num21 - 1, num24, Terrain::MakeBlockValue(contents2));
                            }
                            if (num22 == 2)
                            {
                                chunk->setCellValueFast(num23, num21 - 1, num24, Terrain::MakeBlockValue(contents2));
                            }
                        }
                        else if (num17 < 0.6f)
                        {
                            if (num22 == 0 || num22 == 1)
                            {
                                chunk->setCellValueFast(num23 + p2.posX, num21 - 1, num24 + p2.posZ, Terrain::MakeBlockValue(31, 0, CellFace::Point3ToFace(p2)));
                                chunk->setCellValueFast(num23 - p2.posX, num21 - 1, num24 - p2.posZ, Terrain::MakeBlockValue(31, 0, CellFace::OppositeFace(CellFace::Point3ToFace(p2))));
                            }
                            if (num22 == -1)
                            {
                                chunk->setCellValueFast(num23, num21 - 1, num24, Terrain::MakeBlockValue(31, 0, CellFace::OppositeFace(num9)));
                            }
                            if (num22 == 2)
                            {
                                chunk->setCellValueFast(num23, num21 - 1, num24, Terrain::MakeBlockValue(31, 0, num9));
                            }
                        }
                    }
                    break;
                IL_06ac:;
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateCairns(TerrainChunk *chunk)
    {
        int32_t num = 190;
        Point2 point;
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                if (Terrain::ExtractContents(chunk->getCellValueFast(i, num, j)) == 0)
                {
                    continue;
                }
                for (int32_t k = num + 1; k < 256; k++)
                {
                    if (Terrain::ExtractContents(chunk->getCellValueFast(i, k, j)) == 0)
                    {
                        num = k;
                        point.posX = i;
                        point.posY = j;
                        break;
                    }
                }
            }
        }
        if (num >= 190 && num <= 255 && point.posX >= 1 && point.posX < 15 && point.posY >= 1 && point.posY < 15)
        {
            int32_t data = MathUtils::Clamp((int32_t)(4.0f * MathUtils::LinearStep(190.0f, 256.0f, num)), 0, 3);
            chunk->setCellValueFast(point.posX, num, point.posY, Terrain::MakeBlockValue(258, 0, data));
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateSnowAndIce(TerrainChunk *chunk)
    {
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = i + chunk->origin.posX;
                int32_t num2 = j + chunk->origin.posY;
                for (int32_t num3 = 254; num3 >= 0; num3--)
                {
                    int32_t cellValueFast = chunk->getCellValueFast(i, num3, j);
                    int32_t num4 = Terrain::ExtractContents(cellValueFast);
                    if (num4 != 0)
                    {
                        if (false == SubsystemWeather::IsPlaceFrozen(chunk->getTemperatureFast(i, j), num3))
                        {
                            break;
                        }
                        if (GameSingleton::blocksManager->blocks[num4]->isBlock<WaterBlock *>() == true)
                        {
                            if (calculateOceanShoreDistance(num, num2) > -20.0f)
                            {
                                float num5 = 1 + (int32_t)(2.0f * MathUtils::Sqr(ScSimplexNoise::OctavedNoise(num, num2, 0.2f, 1, 2.0f, 1.0f)));
                                for (int32_t k = 0; (float)k < num5; k++)
                                {
                                    if (num3 - k > 0)
                                    {
                                        if (GameSingleton::blocksManager->blocks[chunk->getCellContentsFast(i, num3 - k, j)]->isBlock<WaterBlock *>() == false)
                                        {
                                            break;
                                        }
                                        chunk->setCellValueFast(i, num3 - k, j, 62);
                                    }
                                }
                                if (SubsystemWeather::ShaftHasSnowOnIce(num, num2))
                                {
                                    chunk->setCellValueFast(i, num3 + 1, j, 61);
                                }
                            }
                        }
                        else if (canSupportSnow(cellValueFast))
                        {
                            chunk->setCellValueFast(i, num3 + 1, j, 61);
                        }
                        if (num4 == 8)
                        {
                            chunk->setCellValueFast(i, num3, j, Terrain::MakeBlockValue(8, 0, 1));
                        }
                        break;
                    }
                }
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::generateBedrockAndAir(TerrainChunk *chunk)
    {
        int32_t value = Terrain::MakeBlockValue(1);
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = i + chunk->origin.posX;
                int32_t num2 = j + chunk->origin.posY;
                float num3 = 2 + (int32_t)(4.0f * ScSimplexNoise::OctavedNoise(num, num2, 0.1f, 1, 1.0f, 1.0f));
                for (int32_t k = 0; (float)k < num3; k++)
                {
                    chunk->setCellValueFast(i, k, j, value);
                }
                chunk->setCellValueFast(i, 255, j, 0);
            }
        }
    }
    // ok
    void NewTerrainContentsGenerator23::updateFluidIsTop(TerrainChunk *chunk)
    {
        for (int32_t i = 0; i < 16; i++)
        {
            for (int32_t j = 0; j < 16; j++)
            {
                int32_t num = TerrainChunk::CalculateCellIndex(i, 255, j);
                int32_t num2 = 0;
                int32_t num3 = 255;
                while (num3 >= 0)
                {
                    int32_t cellValueFast = chunk->getCellValueFast(num);
                    int32_t num4 = Terrain::ExtractContents(cellValueFast);
                    if (num4 != num2 && GameSingleton::blocksManager->blocks[num4]->isBlock<FluidBlock *>() == true && GameSingleton::blocksManager->blocks[num2]->isBlock<FluidBlock *>() == false)
                    {
                        int32_t data = Terrain::ExtractData(cellValueFast);
                        chunk->setCellValueFast(num, Terrain::MakeBlockValue(num4, 0, FluidBlock::SetIsTop(data, true)));
                    }
                    num2 = num4;
                    num3--;
                    num--;
                }
            }
        }
    }

    bool NewTerrainContentsGenerator23::brushIsCreated = false;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::coalBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::ironBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::copperBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::saltpeterBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::sulphurBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::diamondBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::germaniumBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::dirtPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::gravelPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::limestonePocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::sandPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::basaltPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::granitePocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::clayPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::waterPocketBrushes;
    std::vector<TerrainBrush> NewTerrainContentsGenerator23::magmaPocketBrushes;
    std::vector<std::vector<TerrainBrush>> NewTerrainContentsGenerator23::caveBrushesByType;
    // ok
    void NewTerrainContentsGenerator23::CreateBrushes()
    {
        if (brushIsCreated == false)
        {
            brushIsCreated = true;
            Random random(17);

            TBBrush brush(16);
            TBBrush brush2(150);
            for (int32_t i = 0; i < 16; i++)
            {
                TerrainBrush &terrainBrush = coalBrushes.emplace_back();
                int32_t num = random.getInt(4, 12);
                for (int32_t j = 0; j < num; j++)
                {
                    Vector3 vector = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num2 = random.getInt(3, 8);
                    Vector3 zero = FastVector3::Zero;
                    for (int32_t k = 0; k < num2; k++)
                    {

                        terrainBrush.addBox((int32_t)MathUtils::Floor(zero.posX), (int32_t)MathUtils::Floor(zero.posY), (int32_t)MathUtils::Floor(zero.posZ), 1, 1, 1, &brush);
                        zero += vector;
                    }
                }
                if (i == 0)
                {
                    terrainBrush.addCell(0, 0, 0, &brush2);
                }
                terrainBrush.compile();
            }

            brush.value = 39;
            for (int32_t l = 0; l < 16; l++)
            {
                TerrainBrush &terrainBrush2 = ironBrushes.emplace_back();
                int32_t num3 = random.getInt(3, 7);
                for (int32_t m = 0; m < num3; m++)
                {
                    Vector3 vector2 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num4 = random.getInt(3, 6);
                    Vector3 zero2 = FastVector3::Zero;
                    for (int32_t n = 0; n < num4; n++)
                    {
                        terrainBrush2.addBox((int32_t)MathUtils::Floor(zero2.posX), (int32_t)MathUtils::Floor(zero2.posY), (int32_t)MathUtils::Floor(zero2.posZ), 1, 1, 1, &brush);
                        zero2 += vector2;
                    }
                }
                terrainBrush2.compile();
            }

            brush.value = 41;
            for (int32_t num5 = 0; num5 < 16; num5++)
            {
                TerrainBrush &terrainBrush3 = copperBrushes.emplace_back();
                int32_t num6 = random.getInt(4, 10);
                for (int32_t num7 = 0; num7 < num6; num7++)
                {
                    Vector3 vector3 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-2.0f, 2.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num8 = random.getInt(3, 6);
                    Vector3 zero3 = FastVector3::Zero;
                    for (int32_t num9 = 0; num9 < num8; num9++)
                    {
                        terrainBrush3.addBox((int32_t)MathUtils::Floor(zero3.posX), (int32_t)MathUtils::Floor(zero3.posY), (int32_t)MathUtils::Floor(zero3.posZ), 1, 1, 1, &brush);
                        zero3 += vector3;
                    }
                }
                terrainBrush3.compile();
            }

            brush.value = 100;
            for (int32_t num10 = 0; num10 < 16; num10++)
            {
                TerrainBrush &terrainBrush4 = saltpeterBrushes.emplace_back();
                int32_t num11 = random.getInt(8, 16);
                for (int32_t num12 = 0; num12 < num11; num12++)
                {
                    Vector3 vector4 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.25f, 0.25f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num13 = random.getInt(4, 8);
                    Vector3 zero4 = FastVector3::Zero;
                    for (int32_t num14 = 0; num14 < num13; num14++)
                    {
                        terrainBrush4.addBox((int32_t)MathUtils::Floor(zero4.posX), (int32_t)MathUtils::Floor(zero4.posY), (int32_t)MathUtils::Floor(zero4.posZ), 1, 1, 1, &brush);
                        zero4 += vector4;
                    }
                }
                terrainBrush4.compile();
            }

            brush.value = 101;
            for (int32_t num15 = 0; num15 < 16; num15++)
            {
                TerrainBrush &terrainBrush5 = sulphurBrushes.emplace_back();
                int32_t num16 = random.getInt(4, 10);
                for (int32_t num17 = 0; num17 < num16; num17++)
                {
                    Vector3 vector5 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num18 = random.getInt(3, 6);
                    Vector3 zero5 = FastVector3::Zero;
                    for (int32_t num19 = 0; num19 < num18; num19++)
                    {
                        terrainBrush5.addBox((int32_t)MathUtils::Floor(zero5.posX), (int32_t)MathUtils::Floor(zero5.posY), (int32_t)MathUtils::Floor(zero5.posZ), 1, 1, 1, &brush);
                        zero5 += vector5;
                    }
                }
                terrainBrush5.compile();
            }

            brush.value = 112;
            for (int32_t num20 = 0; num20 < 16; num20++)
            {
                TerrainBrush &terrainBrush6 = diamondBrushes.emplace_back();
                int32_t num21 = random.getInt(2, 6);
                for (int32_t num22 = 0; num22 < num21; num22++)
                {
                    Vector3 vector6 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num23 = random.getInt(3, 6);
                    Vector3 zero6 = FastVector3::Zero;
                    for (int32_t num24 = 0; num24 < num23; num24++)
                    {
                        terrainBrush6.addBox((int32_t)MathUtils::Floor(zero6.posX), (int32_t)MathUtils::Floor(zero6.posY), (int32_t)MathUtils::Floor(zero6.posZ), 1, 1, 1, &brush);
                        zero6 += vector6;
                    }
                }
                terrainBrush6.compile();
            }

            brush.value = 148;
            for (int32_t num25 = 0; num25 < 16; num25++)
            {
                TerrainBrush &terrainBrush7 = germaniumBrushes.emplace_back();
                int32_t num26 = random.getInt(4, 10);
                for (int32_t num27 = 0; num27 < num26; num27++)
                {
                    Vector3 vector7 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num28 = random.getInt(3, 6);
                    Vector3 zero7 = FastVector3::Zero;
                    for (int32_t num29 = 0; num29 < num28; num29++)
                    {
                        terrainBrush7.addBox((int32_t)MathUtils::Floor(zero7.posX), (int32_t)MathUtils::Floor(zero7.posY), (int32_t)MathUtils::Floor(zero7.posZ), 1, 1, 1, &brush);
                        zero7 += vector7;
                    }
                }
                terrainBrush7.compile();
            }

            brush.value = 2;
            for (int32_t num30 = 0; num30 < 16; num30++)
            {
                TerrainBrush &terrainBrush8 = dirtPocketBrushes.emplace_back();
                int32_t num31 = random.getInt(16, 32);
                for (int32_t num32 = 0; num32 < num31; num32++)
                {
                    Vector3 vector8 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.75f, 0.75f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num33 = random.getInt(6, 12);
                    Vector3 zero8 = FastVector3::Zero;
                    for (int32_t num34 = 0; num34 < num33; num34++)
                    {
                        terrainBrush8.addBox((int32_t)MathUtils::Floor(zero8.posX), (int32_t)MathUtils::Floor(zero8.posY), (int32_t)MathUtils::Floor(zero8.posZ), 1, 1, 1, &brush);
                        zero8 += vector8;
                    }
                }
                terrainBrush8.compile();
            }

            brush.value = 6;
            for (int32_t num35 = 0; num35 < 16; num35++)
            {
                TerrainBrush &terrainBrush9 = gravelPocketBrushes.emplace_back();
                int32_t num36 = random.getInt(16, 32);
                for (int32_t num37 = 0; num37 < num36; num37++)
                {
                    Vector3 vector9 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.75f, 0.75f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num38 = random.getInt(6, 12);
                    Vector3 zero9 = FastVector3::Zero;
                    for (int32_t num39 = 0; num39 < num38; num39++)
                    {
                        terrainBrush9.addBox((int32_t)MathUtils::Floor(zero9.posX), (int32_t)MathUtils::Floor(zero9.posY), (int32_t)MathUtils::Floor(zero9.posZ), 1, 1, 1, &brush);
                        zero9 += vector9;
                    }
                }
                terrainBrush9.compile();
            }

            brush.value = 66;
            for (int32_t num40 = 0; num40 < 16; num40++)
            {
                TerrainBrush &terrainBrush10 = limestonePocketBrushes.emplace_back();
                int32_t num41 = random.getInt(16, 32);
                for (int32_t num42 = 0; num42 < num41; num42++)
                {
                    Vector3 vector10 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.75f, 0.75f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num43 = random.getInt(6, 12);
                    Vector3 zero10 = FastVector3::Zero;
                    for (int32_t num44 = 0; num44 < num43; num44++)
                    {
                        terrainBrush10.addBox((int32_t)MathUtils::Floor(zero10.posX), (int32_t)MathUtils::Floor(zero10.posY), (int32_t)MathUtils::Floor(zero10.posZ), 1, 1, 1, &brush);
                        zero10 += vector10;
                    }
                }
                terrainBrush10.compile();
            }

            brush.value = 72;
            for (int32_t num45 = 0; num45 < 16; num45++)
            {
                TerrainBrush &terrainBrush11 = clayPocketBrushes.emplace_back();
                int32_t num46 = random.getInt(16, 32);
                for (int32_t num47 = 0; num47 < num46; num47++)
                {
                    Vector3 vector11 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.1f, 0.1f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num48 = random.getInt(6, 12);
                    Vector3 zero11 = FastVector3::Zero;
                    for (int32_t num49 = 0; num49 < num48; num49++)
                    {
                        terrainBrush11.addBox((int32_t)MathUtils::Floor(zero11.posX), (int32_t)MathUtils::Floor(zero11.posY), (int32_t)MathUtils::Floor(zero11.posZ), 1, 1, 1, &brush);
                        zero11 += vector11;
                    }
                }
                terrainBrush11.compile();
            }

            brush.value = 7;
            for (int32_t num50 = 0; num50 < 16; num50++)
            {
                TerrainBrush &terrainBrush12 = sandPocketBrushes.emplace_back();
                int32_t num51 = random.getInt(16, 32);
                for (int32_t num52 = 0; num52 < num51; num52++)
                {
                    Vector3 vector12 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.75f, 0.75f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num53 = random.getInt(6, 12);
                    Vector3 zero12 = FastVector3::Zero;
                    for (int32_t num54 = 0; num54 < num53; num54++)
                    {
                        terrainBrush12.addBox((int32_t)MathUtils::Floor(zero12.posX), (int32_t)MathUtils::Floor(zero12.posY), (int32_t)MathUtils::Floor(zero12.posZ), 1, 1, 1, &brush);
                        zero12 += vector12;
                    }
                }
                terrainBrush12.compile();
            }

            brush.value = 67;
            for (int32_t num55 = 0; num55 < 16; num55++)
            {
                TerrainBrush &terrainBrush13 = basaltPocketBrushes.emplace_back();
                int32_t num56 = random.getInt(16, 32);
                for (int32_t num57 = 0; num57 < num56; num57++)
                {
                    Vector3 vector13 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-0.75f, 0.75f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num58 = random.getInt(6, 12);
                    Vector3 zero13 = FastVector3::Zero;
                    for (int32_t num59 = 0; num59 < num58; num59++)
                    {
                        terrainBrush13.addBox((int32_t)MathUtils::Floor(zero13.posX), (int32_t)MathUtils::Floor(zero13.posY), (int32_t)MathUtils::Floor(zero13.posZ), 1, 1, 1, &brush);
                        zero13 += vector13;
                    }
                }
                terrainBrush13.compile();
            }

            brush.value = 3;
            for (int32_t num60 = 0; num60 < 16; num60++)
            {
                TerrainBrush &terrainBrush14 = granitePocketBrushes.emplace_back();
                int32_t num61 = random.getInt(16, 32);
                for (int32_t num62 = 0; num62 < num61; num62++)
                {
                    Vector3 vector14 = 0.5f * Vector3::Normalize(Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f), random.getFloat(-1.0f, 1.0f)));
                    int32_t num63 = random.getInt(5, 10);
                    Vector3 zero14 = FastVector3::Zero;
                    for (int32_t num64 = 0; num64 < num63; num64++)
                    {
                        terrainBrush14.addBox((int32_t)MathUtils::Floor(zero14.posX), (int32_t)MathUtils::Floor(zero14.posY), (int32_t)MathUtils::Floor(zero14.posZ), 1, 1, 1, &brush);
                        zero14 += vector14;
                    }
                }
                terrainBrush14.compile();
            }

            brush2.value = 0;

            brush.value = 18;
            int32_t array[3]{4, 6, 8};
            for (int32_t num65 = 0; num65 < 4 * (sizeof(array) / sizeof(array[0])); num65++)
            {
                TerrainBrush &terrainBrush15 = waterPocketBrushes.emplace_back();
                int32_t num66 = array[num65 / 4];
                int32_t num67 = num65 % 2 + 1;
                float num68 = ((num65 % 4 == 2) ? 0.5f : 1.0f);
                int32_t num69 = ((num65 % 4 == 1) ? (num66 * num66) : (2 * num66 * num66));
                for (int32_t num70 = 0; num70 < num69; num70++)
                {
                    Vector2 vector15 = random.getVector2(0.0f, num66);
                    float num71 = vector15.length();
                    int32_t num72 = random.getInt(3, 4);
                    int32_t sizeY = 1 + (int32_t)MathUtils::Lerp(MathUtils::Max<float>(num66 / 3.0f, 2.5f) * num68, 0.0f, num71 / (float)num66) + random.getInt(0, 1);

                    terrainBrush15.addBox((int32_t)MathUtils::Floor(vector15.posX), 0, (int32_t)MathUtils::Floor(vector15.posY), num72, sizeY, num72, &brush2);
                    terrainBrush15.addBox((int32_t)MathUtils::Floor(vector15.posX), -num67, (int32_t)MathUtils::Floor(vector15.posY), num72, num67, num72, &brush);
                }
                terrainBrush15.compile();
            }

            brush.value = 92;
            int32_t array2[4]{8, 12, 14, 16};
            for (int32_t num73 = 0; num73 < 4 * (sizeof(array2) / sizeof(array2[0])); num73++)
            {
                TerrainBrush &terrainBrush16 = magmaPocketBrushes.emplace_back();
                int32_t num74 = array2[num73 / 4];
                int32_t num75 = num74 + 2;
                float num76 = ((num73 % 4 == 2) ? 0.5f : 1.0f);
                int32_t num77 = ((num73 % 4 == 1) ? (num74 * num74) : (2 * num74 * num74));
                for (int32_t num78 = 0; num78 < num77; num78++)
                {
                    Vector2 vector16 = random.getVector2(0.0f, num74);
                    float num79 = vector16.length();
                    int32_t num80 = random.getInt(3, 4);
                    int32_t sizeY2 = 1 + (int32_t)MathUtils::Lerp(MathUtils::Max<float>(num74 / 3.0f, 2.5f) * num76, 0.0f, num79 / (float)num74) + random.getInt(0, 1);
                    int32_t num81 = 1 + (int32_t)MathUtils::Lerp(num75, 0.0f, num79 / (float)num74) + random.getInt(0, 1);
                    terrainBrush16.addBox((int32_t)MathUtils::Floor(vector16.posX), 0, (int32_t)MathUtils::Floor(vector16.posY), num80, sizeY2, num80, &brush2);
                    terrainBrush16.addBox((int32_t)MathUtils::Floor(vector16.posX), -num81, (int32_t)MathUtils::Floor(vector16.posY), num80, num81, num80, &brush);
                }
                terrainBrush16.compile();
            }

            for (int32_t num82 = 0; num82 < 7; num82++)
            {
                caveBrushesByType.emplace_back();
                for (int32_t num83 = 0; num83 < 3; num83++)
                {
                    TerrainBrush &terrainBrush17 = caveBrushesByType[num82].emplace_back();
                    int32_t num84 = 6 + 4 * num82;
                    int32_t max = 3 + num82 / 3;
                    int32_t max2 = 9 + num82;
                    for (int32_t num85 = 0; num85 < num84; num85++)
                    {
                        int32_t num86 = random.getInt(2, max);
                        int32_t num87 = random.getInt(8, max2) - 2 * num86;
                        Vector3 vector17 = 0.5f * Vector3(random.getFloat(-1.0f, 1.0f), random.getFloat(0.0f, 1.0f), random.getFloat(-1.0f, 1.0f));
                        Vector3 zero15 = FastVector3::Zero;
                        for (int32_t num88 = 0; num88 < num87; num88++)
                        {
                            terrainBrush17.addBox((int32_t)MathUtils::Floor(zero15.posX) - num86 / 2, (int32_t)MathUtils::Floor(zero15.posY) - num86 / 2, (int32_t)MathUtils::Floor(zero15.posZ) - num86 / 2, num86, num86, num86, &brush2);
                            zero15 += vector17;
                        }
                    }
                    terrainBrush17.compile();
                }
            }
        }
    }
}
